package lumis.content.workflow.serialization;

import lumis.content.ContentManagerFactory;
import lumis.content.workflow.WorkflowConfig;
import lumis.content.workflow.WorkflowPermission;
import lumis.portal.PortalException;
import lumis.portal.PortalObjectNotFoundException;
import lumis.portal.PortalRequestParameters;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.manager.ManagerFactoryInternal;
import lumis.portal.page.PageConfig;
import lumis.portal.principal.PrincipalConfig;
import lumis.portal.progress.ProgressConfig.Type;
import lumis.portal.serialization.BaseSerializationContext;
import lumis.portal.serialization.Dependency;
import lumis.portal.serialization.DeserializationContext;
import lumis.portal.serialization.ExternalDependencyLocalizer;
import lumis.portal.serialization.ISerializationMessageConfigNodeBuilder;
import lumis.portal.serialization.SerializationMessageConfigNode;
import lumis.portal.serialization.SerializationSettings;
import lumis.portal.serialization.DeserializationContext.ImportMemberRules.ForCreate;
import lumis.portal.serialization.DeserializationContext.ImportMemberRules.ForUpdate;
import lumis.portal.serialization.SerializationMessageConfigNode.RecursionStopPoints;
import lumis.portal.serialization.operation.ConfigPersistence;
import lumis.portal.serialization.operation.IConfigPersister;
import lumis.portal.serviceinstance.ServiceInstanceConfig;
import lumis.portal.serviceinstance.serialization.ServiceInstanceBaseSerializationContext;
import lumis.portal.serviceinstance.serialization.ServiceInstanceDeserializationContext;
import lumis.portal.serviceinstance.serialization.ServiceInstanceSerializationContext;
import lumis.util.PortalUtil;
import lumis.util.TextUtil;
import lumis.util.XmlUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;

import org.w3c.dom.Document;

/**
 * Manager for Workflow serialization
 *
 * @version $Revision: 12710 $ $Date: 2011-03-18 17:00:16 -0300 (Fri, 18 Mar 2011) $
 * @since 4.0.7
 */
public class WorkflowSerializationManager implements IWorkflowSerializationManager, IConfigPersister
{
	private class ServiceInstanceWorkflowSerializationMessageConfigNodeBuilder implements ISerializationMessageConfigNodeBuilder
	{
		private BaseSerializationContext baseSerializationContext;
		private ServiceInstanceConfig serviceInstanceConfig;
		private WorkflowPermission workflowPermission;
		private EnumSet<RecursionStopPoints> recursionStopPoints;
		public ServiceInstanceWorkflowSerializationMessageConfigNodeBuilder(BaseSerializationContext baseSerializationContext, ServiceInstanceConfig serviceInstanceConfig, WorkflowPermission workflowPermission, EnumSet<RecursionStopPoints> recursionStopPoints)
		{
			this.baseSerializationContext = baseSerializationContext;	
			this.serviceInstanceConfig = serviceInstanceConfig;	
			this.workflowPermission = workflowPermission;	
			this.recursionStopPoints = recursionStopPoints;	
		}
		public SerializationMessageConfigNode build() throws PortalException
		{
			return getServiceInstanceWorkflowSerializationMessageConfigNode(baseSerializationContext, serviceInstanceConfig, workflowPermission, recursionStopPoints);
		}
	}

	private final String[] permissionForeignKeyFieldNames = new String[] { "serviceInstanceId", "principalId" };

	// DESERIALIZATION
	
	@SuppressWarnings("unchecked")
	public void deserialize(ServiceInstanceDeserializationContext serviceInstanceDeserializationContext, WorkflowSerializableConfig workflowSerializableConfig) throws PortalException
	{
		// update service instance workflow association. Default workflow permissions will be assigned
		String workflowId = null;
		if (workflowSerializableConfig != null)
			workflowId = workflowSerializableConfig.getId();
		serviceInstanceDeserializationContext.logDebug("Deserializing content service instance workflow '" + workflowId + "'");

		// if the service instance workflow does not exist, use null instead to continue deserialization (it will fail on end anyway)
		if (workflowId != null && !analyzeExternalDependency(serviceInstanceDeserializationContext, workflowId))
			workflowId = null;
		ContentManagerFactory.getWorkflowManager().setServiceInstanceWorkflow(serviceInstanceDeserializationContext.getSessionConfig(), serviceInstanceDeserializationContext.getMappedServiceInstanceId(), workflowId, serviceInstanceDeserializationContext.getTransaction());

		if (workflowId != null && (serviceInstanceDeserializationContext.isImportAsChild() || serviceInstanceDeserializationContext.isUpdateIfElementExists())) // merge default permissions with deserialized permissions
		{		
			// deserialize permissions
			ArrayList<WorkflowPermission> deserializedPermissions = getPermissionsBasedOnDeserializationRules(serviceInstanceDeserializationContext, workflowSerializableConfig);
			
			serviceInstanceDeserializationContext.logDebug(" Deserialized workflow permissions", deserializedPermissions);
			
			// check if any principal was not persisted yet
			ArrayList<String> pendentPrincipalIds = new ArrayList(); 
			for (WorkflowPermission permission : deserializedPermissions)
				if (principalExists(serviceInstanceDeserializationContext, permission.getPrincipalId()))
					pendentPrincipalIds.add(permission.getPrincipalId());

			// update the service instance workflow permissions
			WorkflowPermissionPersistenceData workflowPermissionPersistenceData = new WorkflowPermissionPersistenceData(serviceInstanceDeserializationContext.getMappedServiceInstanceId(), deserializedPermissions);
			if (pendentPrincipalIds.size() == 0) // update immediately
			{
				serviceInstanceDeserializationContext.logDebug(" Persisting workflow permissions immediately:", deserializedPermissions);
				ContentManagerFactory.getWorkflowManager().setWorkflowPermissions(serviceInstanceDeserializationContext.getSessionConfig(), serviceInstanceDeserializationContext.getMappedServiceInstanceId(), deserializedPermissions, serviceInstanceDeserializationContext.getTransaction());
			}
			else // update later, when the dependable principals will be already persisted
			{
				serviceInstanceDeserializationContext.logDebug(" Workflow permissions depend on principals " + TextUtil.joinStringCollection(pendentPrincipalIds, ","), deserializedPermissions);
				serviceInstanceDeserializationContext.getDependentConfigPersistences().addDependentConfigOperation(pendentPrincipalIds, new ConfigPersistence(workflowPermissionPersistenceData, this));
			}
		}
	}

	/**
	 * Based on the deserialization rules, workflow permissions are included or removed.
	 * 
	 * @param deserializationContext
	 * @param accessControlList
	 * @param accessControlListSerializableConfig
	 * @throws PortalException
	 * @since 4.2.0
	 */
	private ArrayList<WorkflowPermission> getPermissionsBasedOnDeserializationRules(ServiceInstanceDeserializationContext serviceInstanceDeserializationContext, WorkflowSerializableConfig workflowSerializableConfig) throws PortalException
	{
		ArrayList<WorkflowPermission> deserializedPermissions = new ArrayList<WorkflowPermission>(); 
		
		DeserializationContext deserializationContext = serviceInstanceDeserializationContext.getDeserializationContext();
		ForCreate forCreate = deserializationContext.getImportMemberRules().getForCreate();
		ForUpdate forUpdate = deserializationContext.getImportMemberRules().getForUpdate();

		boolean updating = !serviceInstanceDeserializationContext.isCreating();
		
		if(updating)
		{
			// updating
			Collection<WorkflowPermission> currentPermissions = ContentManagerFactory.getWorkflowManager().getWorkflowPermissions(serviceInstanceDeserializationContext.getSessionConfig(), serviceInstanceDeserializationContext.getMappedServiceInstanceId(), serviceInstanceDeserializationContext.getTransaction());
			
			for(WorkflowPermission currentPermission : currentPermissions)
			{
				boolean deletePermission = false;
			
				// existing permission
				if(forUpdate.equals(ForUpdate.ALL_MEMBERS))
				{
					deletePermission = true;
				}
				else
				{
					PrincipalConfig principalConfig = ManagerFactory.getPrincipalManager().get(deserializationContext.getSessionConfig(), currentPermission.getPrincipalId(), deserializationContext.getTransaction());

					if(principalConfig.getType() == PrincipalConfig.TYPE_GROUP)
					{
						if(forUpdate.equals(ForUpdate.ALL_MEMBERS_OF_TYPE_GROUP) || forUpdate.equals(ForUpdate.ALL_MEMBERS_OF_TYPE_GROUP_IGNORING_NON_EXISTENT_GROUPS))
						{
							deletePermission = true;
						}
						else if(principalConfig.getChannelId() != null)
						{
							// delete only local members
							// make sure the channel id of the member is within the root channel structure.
							String rootChannelMappedId = deserializationContext.getIdMapping(deserializationContext.getRootChannelId());
							String principalChannelMappedId = deserializationContext.getIdMapping(principalConfig.getChannelId());
							if(rootChannelMappedId.equals(principalChannelMappedId) ||
									 ManagerFactory.getChannelManager().getPathIds(deserializationContext.getSessionConfig(), principalChannelMappedId, deserializationContext.getTransaction()).contains(rootChannelMappedId))
								 	deletePermission = true;
						}
					}
				}
				
				if(!deletePermission)
					deserializedPermissions.add(currentPermission);
			}
		}
		
		// now add
		for (WorkflowPermissionSerializableConfig workflowPermissionSerializableConfig : workflowSerializableConfig.getPermissions())
		{
			boolean setPermission = false;

			WorkflowPermission deserializedPermission = deserializePermission(serviceInstanceDeserializationContext, workflowPermissionSerializableConfig);
			
			if( (updating && forUpdate.equals(ForUpdate.ALL_MEMBERS)) ||
					(!updating && forCreate.equals(ForCreate.ALL_MEMBERS)))
			{
				setPermission = true;
			}
			else
			{
				if(workflowPermissionSerializableConfig.getPrincipalType() == PrincipalConfig.TYPE_GROUP)
				{
					if( (updating && forUpdate.equals(DeserializationContext.ImportMemberRules.ForUpdate.ALL_MEMBERS_OF_TYPE_GROUP)) ||
						(!updating && forCreate.equals(DeserializationContext.ImportMemberRules.ForCreate.ALL_MEMBERS_OF_TYPE_GROUP)))
					{
						setPermission = true;
					}
					else if( (updating && forUpdate.equals(DeserializationContext.ImportMemberRules.ForUpdate.ALL_MEMBERS_OF_TYPE_GROUP_IGNORING_NON_EXISTENT_GROUPS)) ||
							(!updating && forCreate.equals(DeserializationContext.ImportMemberRules.ForCreate.ALL_MEMBERS_OF_TYPE_GROUP_IGNORING_NON_EXISTENT_GROUPS)))
					{
						if(workflowPermissionSerializableConfig.isExternal())
						{
							// check if member exists
							try
							{
								setPermission = true;
								ManagerFactory.getGroupManager().get(deserializationContext.getSessionConfig(), deserializedPermission.getPrincipalId(), deserializationContext.getTransaction());
							}
							catch(PortalObjectNotFoundException e)
							{
								setPermission = false;
							}
						}
						else
						{
							setPermission = true;
						}
					}
					else if(workflowPermissionSerializableConfig.getChannelId() != null)
					{
						// adds only local members
						// make sure the channel id of the member is within the root channel structure.
						 String rootChannelMappedId = deserializationContext.getIdMapping(deserializationContext.getRootChannelId());
						String principalChannelMappedId = deserializationContext.getIdMapping(workflowPermissionSerializableConfig.getChannelId());
						if(rootChannelMappedId.equals(principalChannelMappedId) ||
								 ManagerFactory.getChannelManager().getPathIds(deserializationContext.getSessionConfig(), principalChannelMappedId, deserializationContext.getTransaction()).contains(rootChannelMappedId))
							setPermission = true;
					}
				}
			}
			
			if(setPermission)
			{
				deserializedPermissions.add(deserializedPermission);
			}
		}
		
		return deserializedPermissions;
	}
	
	public boolean persistConfig(DeserializationContext deserializationContext, Object config, boolean firstPersistence) throws PortalException
	{
		WorkflowPermissionPersistenceData workflowPermissionPersistenceData = (WorkflowPermissionPersistenceData)config;
		// apply id mappings
		for (WorkflowPermission workflowPermission : workflowPermissionPersistenceData.getDeserializedPermissions())
			deserializationContext.applyForeignKeyFieldIdMappings(workflowPermission, permissionForeignKeyFieldNames);
		deserializationContext.logDebug("Persisting workflow permissions", workflowPermissionPersistenceData.getDeserializedPermissions());
		ContentManagerFactory.getWorkflowManager().setWorkflowPermissions(deserializationContext.getSessionConfig(), workflowPermissionPersistenceData.getServiceInstanceId(), workflowPermissionPersistenceData.getDeserializedPermissions(), deserializationContext.getTransaction());
		return true;
	}

	private boolean analyzeExternalDependency(ServiceInstanceDeserializationContext serviceInstanceDeserializationContext, String workflowId) throws PortalException
	{
		serviceInstanceDeserializationContext.logDebug("Checking workflow '" + workflowId + "' existence");
		boolean workflowExists = false;
		try
		{
			workflowExists = (ContentManagerFactory.getWorkflowManager().getWorkflow(serviceInstanceDeserializationContext.getSessionConfig(), workflowId, serviceInstanceDeserializationContext.getTransaction()) != null);
		}
		catch (PortalObjectNotFoundException e)
		{
		}

		if (!workflowExists)
		{
			serviceInstanceDeserializationContext.logDebug(" Workflow '" + workflowId + "' does not exist. The process will fail on end.");

			// generate a external dependency error message
			ServiceInstanceConfig dependentServiceInstanceConfig = ManagerFactory.getServiceInstanceManager().get(serviceInstanceDeserializationContext.getMappedServiceInstanceId(), serviceInstanceDeserializationContext.getTransaction());

			SerializationMessageConfigNode serializationMessageConfigNode = getWorkflowSerializationMessageConfigNode(workflowId);
			
			Dependency dependency = new Dependency();
			dependency.setDependableNode(serializationMessageConfigNode);
			dependency.setDependentNode(ManagerFactoryInternal.getServiceInstanceSerializationManager().getSerializationMessageConfigNode(serviceInstanceDeserializationContext.getDeserializationContext(), dependentServiceInstanceConfig));

			SerializationSettings serializationSettings = ManagerFactoryInternal.getSerializationManager2().getExternalDependenciesSerializationSettings().clone();
			serializationSettings.getClassAliases().put(WorkflowSerializationMessageConfig.class, "workflow");
			new ExternalDependencyLocalizer(serviceInstanceDeserializationContext.getSessionConfig(), serviceInstanceDeserializationContext.getTransaction()).localizeMessage(dependency);
			String dependencyString = ManagerFactoryInternal.getSerializationManager2().serializeObjectToString(dependency, "dependency", serializationSettings);
			Document dependencyDoc = XmlUtil.getDocument(dependencyString);
			serviceInstanceDeserializationContext.sendProgressNotification(dependencyDoc, "lumis/portal/serialization/style/ExternalDependency.xsl", Type.ERROR);
			serviceInstanceDeserializationContext.setMustRollBack();
		}
		return workflowExists;
	}

	// SERIALIZATION
	public WorkflowSerializableConfig serialize(final ServiceInstanceSerializationContext serviceInstanceSerializationContext) throws PortalException
	{
		final ServiceInstanceConfig serviceInstanceConfig = ManagerFactory.getServiceInstanceManager().get(serviceInstanceSerializationContext.getServiceInstanceId(), serviceInstanceSerializationContext.getTransaction());
		WorkflowSerializableConfig workflowSerializableConfig = null;
		
		// if the service instance has workflow
		WorkflowConfig workflowConfig = ContentManagerFactory.getWorkflowManager().getServiceInstanceWorkflow(serviceInstanceSerializationContext.getSessionConfig(), serviceInstanceSerializationContext.getServiceInstanceId(), serviceInstanceSerializationContext.getTransaction());
		if (workflowConfig != null)
		{
			// build structure object
			workflowSerializableConfig = getSerializableConfig(workflowConfig);
			
			// get workflow permissions
			for (WorkflowPermission permission : ContentManagerFactory.getWorkflowManager().getWorkflowPermissions(serviceInstanceSerializationContext.getSessionConfig(), serviceInstanceSerializationContext.getServiceInstanceId(), serviceInstanceSerializationContext.getTransaction()))
			{
				WorkflowPermissionSerializableConfig workflowPermissionSerializableConfig = serializePermission(serviceInstanceSerializationContext, permission);

				// analyze external dependency
				ISerializationMessageConfigNodeBuilder serializationMessageConfigNodeBuilder = new ServiceInstanceWorkflowSerializationMessageConfigNodeBuilder(serviceInstanceSerializationContext.getSerializationContext(), serviceInstanceConfig, permission, EnumSet.of(RecursionStopPoints.None)); 
				ManagerFactoryInternal.getPrincipalSerializationManager().analyzeExternalDependencies(serviceInstanceSerializationContext.getSerializationContext(), serializationMessageConfigNodeBuilder, permission.getPrincipalId());
				
				workflowSerializableConfig.getPermissions().add(workflowPermissionSerializableConfig);
			}
			
			// register external dependency
			if (!"lumis.standardworkflow".equals(workflowConfig.getId()))
				registerExternalDependency(serviceInstanceSerializationContext, workflowConfig);
		}

		return workflowSerializableConfig;
	}

	protected SerializationMessageConfigNode getWorkflowSerializationMessageConfigNode(String workflowId)
	{
		WorkflowSerializationMessageConfig workflowSerializationMessageConfig = new WorkflowSerializationMessageConfig();
		workflowSerializationMessageConfig.setId(workflowId);
		
		SerializationMessageConfigNode serializationMessageConfigNode = new SerializationMessageConfigNode();
		serializationMessageConfigNode.setNavigateScript(null);
		serializationMessageConfigNode.setSerializationMessageConfig(workflowSerializationMessageConfig);
		return serializationMessageConfigNode;
	}

	protected SerializationMessageConfigNode getServiceInstanceWorkflowSerializationMessageConfigNode(BaseSerializationContext baseSerializationContext, ServiceInstanceConfig serviceInstanceConfig, WorkflowPermission workflowPermission) throws PortalException
	{
		return getServiceInstanceWorkflowSerializationMessageConfigNode(baseSerializationContext, serviceInstanceConfig, workflowPermission, EnumSet.of(RecursionStopPoints.None));
	}

	protected SerializationMessageConfigNode getServiceInstanceWorkflowSerializationMessageConfigNode(BaseSerializationContext baseSerializationContext, ServiceInstanceConfig serviceInstanceConfig, WorkflowPermission workflowPermission, EnumSet<RecursionStopPoints> recursionStopPoints) throws PortalException
	{
		ServiceInstanceWorkflowSerializationMessageConfig serviceInstanceWorkflowSerializationMessageConfig = new ServiceInstanceWorkflowSerializationMessageConfig();
		serviceInstanceWorkflowSerializationMessageConfig.setId(null);

		SerializationMessageConfigNode serializationMessageConfigNode = new SerializationMessageConfigNode();
		serializationMessageConfigNode.setSerializationMessageConfig(serviceInstanceWorkflowSerializationMessageConfig);
		serializationMessageConfigNode.getParentNodes().add(getWorkflowSerializationMessageConfigNode(workflowPermission.getWorkflowId()));
		serializationMessageConfigNode.getParentNodes().add(ManagerFactoryInternal.getServiceInstanceSerializationManager().getSerializationMessageConfigNode(baseSerializationContext, serviceInstanceConfig, recursionStopPoints));
		serializationMessageConfigNode.setNavigateScript("window.parent.opener.open('../../../../" + PageConfig.PAGE_MAIN
				+ "?lumServiceInstanceId=LumisBlankServiceInstance&" + PortalRequestParameters.PAGE_PARAMETER_CHANNELID + "="
				+ serviceInstanceConfig.getChannelId() + "&" + PortalRequestParameters.PAGE_PARAMETER_RUN_TIME_INTERFACE
				+ "=lumis.service.portalmanagement.serviceinstanceacl.administration&serviceInstanceId=" + serviceInstanceConfig.getId()
				+ "','_blank', 'top=10,width=500,height=595,left=20');return false;");
		return serializationMessageConfigNode;
	}
	
	private WorkflowSerializableConfig getSerializableConfig(WorkflowConfig workflowConfig)
	{
		WorkflowSerializableConfig workflowSerializableConfig = new WorkflowSerializableConfig();
		workflowSerializableConfig.setId(workflowConfig.getId());
		return workflowSerializableConfig;
	}

	private void registerExternalDependency(ServiceInstanceSerializationContext serviceInstanceSerializationContext, WorkflowConfig workflowConfig) throws PortalException
	{
		String dependencyKey = WorkflowConfig.class.getName() + workflowConfig.getId();
		if (!serviceInstanceSerializationContext.hasDependency(dependencyKey))
		{
			// generate a external dependency warning message
			ServiceInstanceConfig dependentServiceInstanceConfig = ManagerFactory.getServiceInstanceManager().get(serviceInstanceSerializationContext.getServiceInstanceId(), serviceInstanceSerializationContext.getTransaction());
			
			WorkflowSerializationMessageConfig workflowSerializationMessageConfig = new WorkflowSerializationMessageConfig();
			workflowSerializationMessageConfig.setId(workflowConfig.getId());
			
			SerializationMessageConfigNode serializationMessageConfigNode = new SerializationMessageConfigNode();
			serializationMessageConfigNode.setNavigateScript(null);
			serializationMessageConfigNode.setSerializationMessageConfig(workflowSerializationMessageConfig);
			
			Dependency dependency = new Dependency();
			dependency.setDependableNode(serializationMessageConfigNode);
			dependency.setDependentNode(ManagerFactoryInternal.getServiceInstanceSerializationManager().getSerializationMessageConfigNode(serviceInstanceSerializationContext.getSerializationContext(), dependentServiceInstanceConfig));

			SerializationSettings serializationSettings = ManagerFactoryInternal.getSerializationManager2().getExternalDependenciesSerializationSettings().clone();
			serializationSettings.getClassAliases().put(WorkflowSerializationMessageConfig.class, "workflow");
			new ExternalDependencyLocalizer(serviceInstanceSerializationContext.getSessionConfig(), serviceInstanceSerializationContext.getTransaction()).localizeMessage(dependency);
			String dependencyString = ManagerFactoryInternal.getSerializationManager2().serializeObjectToString(dependency, "dependency", serializationSettings);
			Document dependencyDoc = XmlUtil.getDocument(dependencyString);
			serviceInstanceSerializationContext.sendProgressNotification(dependencyDoc, "lumis/portal/serialization/style/ExternalDependency.xsl", Type.WARNING);
		}
	}

	// PERMISSION DESERIALIZATION
	
	private WorkflowPermission deserializePermission(ServiceInstanceDeserializationContext serviceInstanceDeserializationContext, WorkflowPermissionSerializableConfig workflowPermissionSerializableConfig) throws PortalException
	{
		// deserialize permission
		WorkflowPermission workflowPermission = ManagerFactoryInternal.getSerializationManager2().deserializeObject(WorkflowPermission.class, serviceInstanceDeserializationContext.getStructureDirectory(), getWorkflowPermissionPath(workflowPermissionSerializableConfig.getId()), null, serviceInstanceDeserializationContext.getSerializationSettings(), false);
		
		// apply id mappings
		serviceInstanceDeserializationContext.applyForeignKeyFieldIdMappings(workflowPermission, permissionForeignKeyFieldNames);
		
		return workflowPermission;
	}

	// PERMISSION SERIALIZATION
	
	private WorkflowPermissionSerializableConfig serializePermission(ServiceInstanceSerializationContext serviceInstanceSerializationContext, WorkflowPermission permission) throws PortalException
	{
		// generate a permission id
		String permissionId = PortalUtil.generateNewGuid();

		// build structure object
		WorkflowPermissionSerializableConfig permissionSerializableConfig = getPermissionSerializableConfig(serviceInstanceSerializationContext, permissionId, permission);

		// serialize permission
		ManagerFactoryInternal.getSerializationManager2().serializeObject(permission, serviceInstanceSerializationContext.getStructureDirectory(), getWorkflowPermissionPath(permissionId), null);
		
		// return structure object
		return permissionSerializableConfig;
	}
	
	private WorkflowPermissionSerializableConfig getPermissionSerializableConfig(ServiceInstanceSerializationContext serviceInstanceSerializationContext, String permissionId, WorkflowPermission permission) throws PortalException
	{
		WorkflowPermissionSerializableConfig workflowPermissionSerializableConfig = new WorkflowPermissionSerializableConfig();
		workflowPermissionSerializableConfig.setId(permissionId);
		PrincipalConfig principalConfig = ManagerFactory.getPrincipalManager().get(serviceInstanceSerializationContext.getSessionConfig(), permission.getPrincipalId(), serviceInstanceSerializationContext.getTransaction());
		workflowPermissionSerializableConfig.setPrincipalType(principalConfig.getType());
		workflowPermissionSerializableConfig.setChannelId(principalConfig.getChannelId());
		
		workflowPermissionSerializableConfig.setExternal(!serviceInstanceSerializationContext.getSerializationContext().getChannelIds().contains(principalConfig.getChannelId()) && !serviceInstanceSerializationContext.getSerializationContext().getGlobalGroups().contains(permission.getPrincipalId()));
		
		return workflowPermissionSerializableConfig;
	}
	
	// GENERAL 

	public void setupSerializationContext(ServiceInstanceBaseSerializationContext serviceInstanceBaseSerializationContext)
	{
		Map<Class, String> classAliases = serviceInstanceBaseSerializationContext.getSerializationSettings().getClassAliases();
		classAliases.put(WorkflowSerializableConfig.class, "workflow");
		classAliases.put(WorkflowPermission.class, "workflowPermission");
		classAliases.put(WorkflowPermissionSerializableConfig.class, "permission");
	}

	private String getWorkflowPermissionPath(String workflowPermissionId)
	{
		return "/ContentService/workflows/" + workflowPermissionId + ".xml";
	}
	
	private boolean principalExists(ServiceInstanceDeserializationContext serviceInstanceDeserializationContext, String principalId) throws PortalException
	{
		PrincipalConfig principalConfig = null;
		try
		{
			principalConfig = ManagerFactory.getPrincipalManager().get(serviceInstanceDeserializationContext.getSessionConfig(), principalId, serviceInstanceDeserializationContext.getTransaction());
		}
		catch (PortalObjectNotFoundException e)
		{
		}
		return principalConfig != null;
	}

}
